package 多线程;

import java.util.logging.Level;
import java.util.logging.Logger;

/*
Java提供了很丰富的API但没有为停止线程提供API。JDK 1.0本来有一些像stop(), suspend() 和 resume()的控制方法,
但是由于潜在的死锁威胁因此在后续的JDK版本中他们被弃用了，之后Java API的设计者就没有提供一个兼容且线程安全的方法
来停止一个线程。

一种流行的安全停止线程的方法是：使用boolean变量来停止java中线程。安全是因为它不执行任何特殊的操作，
只是帮助run ()方法来停止它本身。
 */
public class StopAThread  extends Thread{
    //控制退出线程的布尔变量
    boolean bExit = false;

    public void exit(boolean bExit){
        this.bExit = bExit;
    }

    @Override
    public void run(){
        //问题1：如何终止一个正常运行的线程？
        while(!bExit){

            System.out.println("Thread is running");
            //问题2：由于异常导致线程终止时，只是线程终止还是整个java程序都终止了？
//            int i=1/0;  //实验发现，run()方法中的异常导致线程终止时，会调用
              // Thread.UncaughtExceptionHandler(thread,throwable)未捕获异常处理程序，
              // 此处理程序会打印异常信息，由于异常已经被处理了，JVM会忽略这个异常，继续执行后面的程序。

            try {
//                Thread.sleep(500);  //sleep()会抛出InterruptedException异常，必须捕获
                this.wait(500); //wait()会抛出InterruptedException异常，必须捕获,
                    // 且必须通过notify()或notifyAll()才能唤醒
                 //1、但是有一个问题，wait()方法必须放在在获得当前对象锁的情况下，因为wait()即强制释放当前线程拥有的对象锁。
                 //在这个run()方法中调用wait()方法，由于没有获得对象锁，会报错ava.lang.IllegalMonitorStateException(原则上
                // wait方法必须在同步方法获得同步代码块中调用，因为进入这些代码块中的线程必须已经获得对象锁)
                //2、接着上一步的问题：既然会抛出异常，那么程序会终止运行吗？
                //答案是不会。这里涉及到一个问题，当线程中的异常没有被程序员主动处理时，JVM会调用Thread.UncaughtExceptionHandler接口
                //中的uncaughtException(thread,throwable)未捕获异常处理程序进行处理，并打印异常信息。
            } catch (InterruptedException ex) {
                Logger.getLogger(StopAThread.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
}
